gboolean use_custom_surface;
+ guint32 scale;
gboolean pending_commit;
gint64 pending_frame_counter;
};
GdkWindowImplClass parent_class;
};
+static void gdk_wayland_window_configure (GdkWindow *window,
+ int width, int height, int edges);
+
G_DEFINE_TYPE (GdkWindowImplWayland, _gdk_window_impl_wayland, GDK_TYPE_WINDOW_IMPL)
static void
_gdk_window_impl_wayland_init (GdkWindowImplWayland *impl)
{
+ impl->scale = 1;
}
void
struct wl_buffer *buffer;
GdkWaylandDisplay *display;
int32_t width, height;
+ uint32_t scale;
gboolean busy;
} GdkWaylandCairoSurfaceData;
data->busy = TRUE;
}
+static void
+window_update_scale (GdkWindow *window)
+{
+ GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
+ GdkWaylandDisplay *wayland_display = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
+ guint32 scale;
+ GSList *l;
+
+ scale = 1;
+ for (l = impl->outputs; l != NULL; l = l->next)
+ {
+ guint32 output_scale =
+ _gdk_wayland_screen_get_output_scale (wayland_display->screen,
+ l->data);
+ scale = MAX (scale, output_scale);
+ }
+
+#ifndef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
+ /* Don't announce a scale if we can't support it */
+ scale = 1;
+#endif
+
+ if (scale != impl->scale)
+ {
+ impl->scale = scale;
+
+ /* Notify app that scale changed */
+ gdk_wayland_window_configure (window, window->width, window->height, impl->resize_edges);
+ }
+}
+
+static void
+on_monitors_changed (GdkScreen *screen,
+ GdkWindow *window)
+{
+ window_update_scale (window);
+}
+
void
_gdk_wayland_display_create_window_impl (GdkDisplay *display,
GdkWindow *window,
g_object_ref (window);
+ /* More likely to be right than just assuming 1 */
+ impl->scale = gdk_screen_get_monitor_scale_factor (screen, 0);
+
impl->title = NULL;
switch (GDK_WINDOW_TYPE (window))
G_CALLBACK (on_frame_clock_before_paint), window);
g_signal_connect (frame_clock, "after-paint",
G_CALLBACK (on_frame_clock_after_paint), window);
+
+ g_signal_connect (screen, "monitors-changed",
+ G_CALLBACK (on_monitors_changed), window);
}
static void
/* Attach this new buffer to the surface */
wl_surface_attach (impl->surface, data->buffer, dx, dy);
+ wl_surface_set_buffer_scale (impl->surface, data->scale);
+
impl->pending_commit = TRUE;
}
static cairo_surface_t *
gdk_wayland_create_cairo_surface (GdkWaylandDisplay *display,
- int width, int height)
+ int width, int height, guint scale)
{
GdkWaylandCairoSurfaceData *data;
cairo_surface_t *surface = NULL;
data->buffer = NULL;
data->width = width;
data->height = height;
+ data->scale = scale;
data->busy = FALSE;
stride = width * 4;
data->pool = _create_shm_pool (display->shm,
- width, height,
+ width*scale, height*scale,
&data->buf_length,
&data->buf);
data->buffer = wl_shm_pool_create_buffer (data->pool, 0,
- width, height,
- stride, WL_SHM_FORMAT_ARGB8888);
+ width*scale, height*scale,
+ stride*scale, WL_SHM_FORMAT_ARGB8888);
wl_buffer_add_listener (data->buffer, &buffer_listener, data);
surface = cairo_image_surface_create_for_data (data->buf,
CAIRO_FORMAT_ARGB32,
- width,
- height,
- stride);
+ width*scale,
+ height*scale,
+ stride*scale);
cairo_surface_set_user_data (surface, &gdk_wayland_cairo_key,
data, gdk_wayland_cairo_surface_destroy);
+#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
+ cairo_surface_set_device_scale (surface, scale, scale);
+#endif
+
status = cairo_surface_status (surface);
if (status != CAIRO_STATUS_SUCCESS)
{
impl->cairo_surface =
gdk_wayland_create_cairo_surface (display_wayland,
- impl->wrapper->width,
- impl->wrapper->height);
+ impl->wrapper->width,
+ impl->wrapper->height,
+ impl->scale);
}
}
display = gdk_window_get_display (window);
- /* TODO: Only generate a configure event if width or height have actually
+ /* TODO: Only generate a configure event if width/height/scale have actually
* changed?
*/
event = gdk_event_new (GDK_CONFIGURE);
GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
impl->outputs = g_slist_prepend (impl->outputs, output);
+
+ window_update_scale (window);
}
static void
GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
impl->outputs = g_slist_remove (impl->outputs, output);
+
+ window_update_scale (window);
}
+
static void
shell_surface_handle_configure(void *data,
struct wl_shell_surface *shell_surface,
{
}
+static gint
+gdk_wayland_window_get_scale_factor (GdkWindow *window)
+{
+ GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return 1;
+
+ return impl->scale;
+}
+
+
static void
_gdk_window_impl_wayland_class_init (GdkWindowImplWaylandClass *klass)
{
impl_class->get_property = gdk_wayland_window_get_property;
impl_class->change_property = gdk_wayland_window_change_property;
impl_class->delete_property = gdk_wayland_window_delete_property;
+ impl_class->get_scale_factor = gdk_wayland_window_get_scale_factor;
}